use async_trait::async_trait;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::error::Error;
use std::collections::HashMap;
use crate::config::data_source_config::DataSourceConfig;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StockQuote {
    pub symbol: String,
    pub timestamp: DateTime<Utc>,
    pub price: f64,
    pub volume: f64,
    pub amount: f64,
    pub bid_price: f64,
    pub ask_price: f64,
    pub bid_volume: f64,
    pub ask_volume: f64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SectorIndex {
    pub code: String,
    pub name: String,
    pub value: f64,
    pub change: f64,
    pub change_percent: f64,
    pub timestamp: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MarketSentiment {
    pub timestamp: DateTime<Utc>,
    pub fear_greed_index: f64,
    pub put_call_ratio: f64,
    pub vix: Option<f64>,
    pub bullish_percent: Option<f64>,
    pub bearish_percent: Option<f64>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VolumeDistribution {
    pub timestamp: DateTime<Utc>,
    pub total_volume: f64,
    pub up_volume: f64,
    pub down_volume: f64,
    pub distribution: HashMap<String, f64>, // 成交量分布，如按价格区间
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MarketBreadth {
    pub timestamp: DateTime<Utc>,
    pub advancing_issues: i32,
    pub declining_issues: i32,
    pub unchanged_issues: i32,
    pub new_highs: i32,
    pub new_lows: i32,
    pub advance_decline_ratio: f64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VolatilityIndex {
    pub timestamp: DateTime<Utc>,
    pub historical_volatility: f64,
    pub implied_volatility: f64,
    pub name: String,
}

#[async_trait]
pub trait DataSource: Send + Sync {
    async fn get_stock_quote(&self, symbol: &str) -> Result<StockQuote, Box<dyn Error + Send + Sync>>;
    
    async fn get_sector_indices(&self) -> Result<Vec<SectorIndex>, Box<dyn Error + Send + Sync>>;
    
    async fn get_market_sentiment(&self) -> Result<MarketSentiment, Box<dyn Error + Send + Sync>>;
    
    async fn get_volume_distribution(&self) -> Result<VolumeDistribution, Box<dyn Error + Send + Sync>>;
    
    async fn get_market_breadth(&self) -> Result<MarketBreadth, Box<dyn Error + Send + Sync>>;
    
    async fn get_volatility_indices(&self) -> Result<Vec<VolatilityIndex>, Box<dyn Error + Send + Sync>>;
    
    fn name(&self) -> &str;
}

pub mod tdx;
pub mod akshare;

pub fn create_data_source(config: &DataSourceConfig) -> Box<dyn DataSource> {
    match config.source_type.as_str() {
        "tdx" => Box::new(tdx::TdxDataSource::new(config)),
        "akshare" => Box::new(akshare::AkShareDataSource::new(config)),
        _ => panic!("Unsupported data source type: {}", config.source_type),
    }
}